package com.baikeyang.bike.service.impl;

import java.util.*;
import java.util.Map.Entry;

import com.baikeyang.bike.common.Constants;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.baikeyang.bike.bean.BikeBean;
import com.baikeyang.bike.bean.ConvertLocalReuslt;
import com.baikeyang.bike.service.IXABikeService;
import com.baikeyang.bike.util.HttpClientUtils;
import com.baikeyang.bike.util.RedisUtil;
import com.baikeyang.bike.util.StringUtil;
import com.baikeyang.bike.ws.client.xabike.findabnormalsite.IAbnormalSiteService;
import com.baikeyang.bike.ws.client.xabike.findabnormalsite.IAbnormalSiteServicePortType;
import com.baikeyang.bike.ws.client.xabike.findbike.IBikeSitesService;
import com.baikeyang.bike.ws.client.xabike.findbike.IBikeSitesServicePortType;
import com.baikeyang.bike.ws.client.xabike.tradecount.IBikeTradeCountService;
import com.baikeyang.bike.ws.client.xabike.tradecount.IBikeTradeCountServicePortType;
import com.baikeyang.bike.ws.client.xabike.traderecord.IBikeTradeRecordService;
import com.baikeyang.bike.ws.client.xabike.traderecord.IBikeTradeRecordServicePortType;

@Service("xaBikeService")
public class XABikeServiceImpl implements IXABikeService {
	
	private static final Logger logger = Logger.getLogger(XABikeServiceImpl.class);

	@Override
	public void sayHello(String str) {
		IBikeTradeCountServicePortType bikeService = new IBikeTradeCountService().getIBikeTradeCountServiceHttpPort();
		String bikeCount = bikeService.findBikeTradeCount();
		System.out.println(bikeCount);
		System.out.println("你要说的话是:"+str);
	}

	/**
	 * 查询昨日租车数量
	 * @return
	 */
	@Override
	public String findBikeTradeCount() {
		IBikeTradeCountServicePortType bikeService = new IBikeTradeCountService().getIBikeTradeCountServiceHttpPort();
		String bikeCount = bikeService.findBikeTradeCount();
		return bikeCount;
	}

	/**
	 * 查询正常站点信息(由于是从官方获取信息，所以该接口信息获取过于缓慢)
	 * @return
	 */
	@Override
	public String findBikeNormalSite(){
		IBikeSitesServicePortType bikeSiteService = new IBikeSitesService().getIBikeSitesServiceHttpPort();
		String bikeSite = bikeSiteService.findBikeSites();
		return bikeSite;
	}

	/**
	 * 获取所有正常站点信息(该接口直接从Redis中获取数据)
	 * @return
	 */
	@Override
	public List<BikeBean> getBikeNormalSite(){
		List<BikeBean> bikesNormal = new ArrayList<BikeBean>();
		try {
			String key = "bike-normal-position";
			Map<String, String> keys = RedisUtil.hgetKeys(key);
			Iterator<Entry<String, String>> iterator = keys.entrySet().iterator();
			while(iterator.hasNext()){
				Entry<String, String> en = iterator.next();
				String siteid = en.getKey();
				String value = RedisUtil.getString("bike-site-"+siteid);
				if(StringUtil.isNotEmpty(value)){
					bikesNormal.add(JSON.parseObject(value, BikeBean.class));
				}
			}
		} catch (Exception e) {
			logger.error("获取正常车辆站点时发生异常", e);
		}
		return bikesNormal;
	}

	/**
	 * 查询异常站点信息(由于是从官方获取信息，该接口信息获取过于缓慢)
	 * @return
	 */
	@Override
	public String findBikeAbnormalSite(){
		IAbnormalSiteServicePortType abnormalSite = new IAbnormalSiteService().getIAbnormalSiteServiceHttpPort();
		String bikeSite = abnormalSite.findAbnormalSites();
		return bikeSite;
	}

	/**
	 * 获取所有异常站点信息(该接口直接从Redis中获取数据)
	 * @return
	 */
	public List<BikeBean> getBikeAbnormalSite(){
		List<BikeBean> bikesAbnormal = new ArrayList<BikeBean>();
		try {
			String key = "bike-abnormal-position";
			Map<String, String> keys = RedisUtil.hgetKeys(key);
			Iterator<Entry<String, String>> iterator = keys.entrySet().iterator();
			while(iterator.hasNext()){
				Entry<String, String> en = iterator.next();
				String siteid = en.getKey();
				String value = RedisUtil.getString("bike-site-"+siteid);
				if(StringUtil.isNotEmpty(value)){
					bikesAbnormal.add(JSON.parseObject(value, BikeBean.class));
				}
			}
		} catch (Exception e) {
			logger.error("获取异常车辆站点时发生异常", e);
		}
		return bikesAbnormal;
	}

	/**
	 * 根据卡号查询租赁历史记录
	 * @param cardNo
	 * @return
	 */
	@Override
	public String findBikeTradeRecords(String cardNo) {
		if(StringUtil.isNotEmpty(cardNo)){
			IBikeTradeRecordServicePortType tradeRecordSerivce = new IBikeTradeRecordService().getIBikeTradeRecordServiceHttpPort();
			String tradeRecord = tradeRecordSerivce.findBikeTradeRecords(cardNo);
			try{
				if(StringUtil.isNotEmpty(tradeRecord)){
					List<Object> lists = (List)JSONArray.parseArray(tradeRecord, List.class);
					if(!CollectionUtils.isEmpty(lists)){
						lists = lists.subList(0, 50);
						tradeRecord = JSONArray.toJSON(lists).toString();
					}
				}
			}catch(Exception e) {
				logger.error("处理租赁记录时发生异常", e);
			}
			return tradeRecord;
		}else{
			return "";
		}
	}

	public static void main(String[] args) throws Exception{
//		XABikeServiceImpl im = new XABikeServiceImpl();
//		String records = im.findBikeTradeRecords("07405244");
//		List<Object> lists = (List)JSONArray.parseArray(records, List.class);
//		System.out.println(lists.size());
//		lists = lists.subList(0, 50);
//		System.out.println(JSONArray.toJSON(lists));

		List<String> fields = new ArrayList<String>();
		List<String> values = new ArrayList<String>();

		for(int i = 60;i < 70; i++){
			fields.add(i+"");
			values.add(i+"_test"+"YYY");
		}

		//RedisUtil.del("bike-hash-test");
		String[] fieldsArray = new String[]{};
		RedisUtil.hdel("bike-hash-test", fields.toArray(fieldsArray));
		//RedisUtil.setHSet("bike-hash-test", fields, values);

	}
	
	@Override
	public void synchronizeBikeSitePosition() throws Exception {
		long time = System.currentTimeMillis();
		synchronizeBikeAbnormalSitePosition();// 异常站点信息
		synchronizeBikeNormalSitePosition();// 正常站点信息
		long enttime = System.currentTimeMillis();
		System.out.println(enttime - time);
	}

	/**
	 * 异常站点信息同步至Redis
	 * @throws Exception
	 */
	private void synchronizeBikeAbnormalSitePosition() throws Exception {
		try {
			List<String> fields = new ArrayList<String>();
			List<String> values = new ArrayList<String>();
			// 异常站点
			String abnormal = findBikeAbnormalSite();
			List<BikeBean> bikesAbnormal  = JSONArray.parseArray(abnormal, BikeBean.class);

			for (int i = 0; i < bikesAbnormal.size(); i++) {
				BikeBean bike = bikesAbnormal.get(i);
				if(null != bike){
					fields.add(bike.getSiteid());
					values.add(bike.getLongitude() + "," + bike.getLatitude());
				}
			}
			logger.debug("Abnormal：本次共同步[原始数据源]" + fields.size() + "条数据。");
			RedisUtil.del(Constants.RedisKey.异常车辆);
			RedisUtil.setHSet(Constants.RedisKey.异常车辆, fields, values);

			
			fields = new ArrayList<String>();
	        values = new ArrayList<String>();
	        List<BikeBean> bikesNormalByAmap = bikeLocalConvert(bikesAbnormal, null, 2);
	        for(BikeBean bike:bikesNormalByAmap){
				if(null != bike){
					fields.add(bike.getSiteid());
					values.add(bike.getLongitude() + "," + bike.getLatitude());
				}
			}
	        logger.debug("Abnormal：本次共同步[高德数据源]" + fields.size() + "条数据。");
			RedisUtil.del(Constants.RedisKey.异常车辆AMAP);
			RedisUtil.setHSet(Constants.RedisKey.异常车辆AMAP, fields, values);
			
        } catch (Exception e) {
        	logger.error("车站位置信息 数据同步异常.", e);
        }
	}

	/**
	 * 正常站点信息同步至Redis
	 * @throws Exception
	 */
	private void synchronizeBikeNormalSitePosition() throws Exception {

		try {
			List<String> fields = new ArrayList<String>();
			List<String> values = new ArrayList<String>();
			// 正常站点
			String normal = findBikeNormalSite();
			List<BikeBean> bikesNormal = JSONArray.parseArray(normal, BikeBean.class);
			for (int i = 0; i < bikesNormal.size(); i++) {
				BikeBean bike = bikesNormal.get(i);
				if(null != bike){
					fields.add(bike.getSiteid());
					values.add(bike.getLongitude() + "," + bike.getLatitude());
				}
			}
			logger.debug("Normal：本次共同步[原始数据源]" + fields.size() + "条数据。");
			RedisUtil.del(Constants.RedisKey.正常车辆);
			RedisUtil.setHSet(Constants.RedisKey.正常车辆, fields, values);

			fields = new ArrayList<String>();
	        values = new ArrayList<String>();
	        List<BikeBean> bikesNormalByAmap = bikeLocalConvert(bikesNormal, null, 2);
			for(BikeBean bike:bikesNormalByAmap){
				if(null != bike){
					fields.add(bike.getSiteid());
					values.add(bike.getLongitude() + "," + bike.getLatitude());
				}
			}
			logger.debug("Normal：本次共同步[高德数据源]" + fields.size() + "条数据。");
			RedisUtil.del(Constants.RedisKey.正常车辆AMAP);
			RedisUtil.setHSet(Constants.RedisKey.正常车辆AMAP, fields, values);

        } catch (Exception e) {
        	logger.error("车站位置信息 数据同步异常.", e);
        }
	}

	@Override
	public void synchronizeBikeSite() {
		synchronizeBikeNormalSite();
		synchronizeBikeAbnormalSite();
	}
	
	public void synchronizeBikeNormalSite(){
		List<String> keys = new ArrayList<String>();
        List<String> values = new ArrayList<String>();
		// 正常站点
		String normal = findBikeNormalSite();
		List<BikeBean> bikesNormal = JSONArray.parseArray(normal, BikeBean.class);
		for (int i = 0; i < bikesNormal.size(); i++) {
			BikeBean bike = bikesNormal.get(i);
			if(null != bike){
				String key = "bike-site-"+bike.getSiteid();
				keys.add(key);
				bike.setSiteState("1");
				values.add(JSON.toJSONString(bike));
			}
		}
		try {
            RedisUtil.setStrings(keys, values);
        } catch (Exception e) {
        	logger.error("同步 正常车辆信息 数据异常.", e);
        }
	}
	
	public void synchronizeBikeAbnormalSite(){
		List<String> keys = new ArrayList<String>();
        List<String> values = new ArrayList<String>();
        // 异常站点
		String abnormal = findBikeAbnormalSite();
		List<BikeBean> bikesAbnormal  = JSONArray.parseArray(abnormal, BikeBean.class);
		for (int i = 0; i < bikesAbnormal.size(); i++) {
			BikeBean bike = bikesAbnormal.get(i);
			if(null != bike){
				// {"emptynum":"10","latitude":"34.347436","location":"","locknum":"20","longitude":"108.96173","siteState":"1","siteid":"1003","sitename":"市人大"}
				String key = "bike-site-"+bike.getSiteid();
				keys.add(key);
				bike.setSiteState("0");
				values.add(JSON.toJSONString(bike));
			}
		}
		try {
            RedisUtil.setStrings(keys, values);
        } catch (Exception e) {
        	logger.error("同步 异常车辆信息 数据异常.", e);
        }
	}

	@Override
	public List<BikeBean> getAllBikes() throws Exception {
		List<BikeBean> bikes = new ArrayList<BikeBean>();
		String key = "bike-site-*";
		Set<String> keys = RedisUtil.getKeys(key);
		Iterator<String> it = keys.iterator();
		while (it.hasNext()) {  
			String str = it.next();
			String value = RedisUtil.getString(str);
			BikeBean bb = new BikeBean();
			bb = JSON.parseObject(value, BikeBean.class);
			bikes.add(bb);
		}
		return bikes;
	}
	
	public List<BikeBean> getAllBikePostions(int convertType) {
		List<BikeBean> bikes = new ArrayList<BikeBean>();

		// 开始获取异常站点位置信息
		try {
			String abnormalKey = Constants.RedisKey.异常车辆;
			if(convertType == 1){
				//abnormalKey = "bike-abnormal-position-qqmap";
				abnormalKey = Constants.RedisKey.异常车辆AMAP;
			}else if(convertType == 2){
				abnormalKey = Constants.RedisKey.异常车辆AMAP;
			}
			
			Map<String, String> abnormalKeys = RedisUtil.hgetKeys(abnormalKey);
			Iterator<Entry<String, String>> it = abnormalKeys.entrySet().iterator();
			while(it.hasNext()){
				Entry<String, String> en = it.next();
				BikeBean bb = new BikeBean();
				bb.setSiteState("0");
				bb.setSiteid(en.getKey());
				if(StringUtil.isNotEmpty(en.getValue())){
					try{
						bb.setLongitude(en.getValue().split(",")[0]);
						bb.setLatitude(en.getValue().split(",")[1]);
					}catch(Exception e){
						System.out.println(en.getValue());
					}
				}
				bikes.add(bb);
			}
			
		} catch (Exception e) {
			logger.error("获取异常站点位置信息时发生异常", e);
		}
		try {
			String normalKey = Constants.RedisKey.正常车辆;
			if(convertType == 1){
				normalKey = Constants.RedisKey.正常车辆AMAP;
			}else if(convertType == 2){
				normalKey = Constants.RedisKey.正常车辆AMAP;
			}
			Map<String, String> normalKeys = RedisUtil.hgetKeys(normalKey);
			Iterator<Entry<String, String>> it = normalKeys.entrySet().iterator();
			while(it.hasNext()){
				Entry<String, String> en = it.next();
				BikeBean bb = new BikeBean();
				bb.setSiteState("1");
				bb.setSiteid(en.getKey());
				if(StringUtil.isNotEmpty(en.getValue())){
					try{
						bb.setLongitude(en.getValue().split(",")[0]);
						bb.setLatitude(en.getValue().split(",")[1]);
					}catch(Exception e){
						System.out.println(en.getValue());
					}
				}
				bikes.add(bb);
			}
		} catch (Exception e) {
			logger.error("获取正常站点位置信息时发生异常", e);
		}
		return bikes;
	}

	@Override
	public BikeBean getBikeSiteById(String siteId) {
		BikeBean bb = new BikeBean();
		if(StringUtil.isNotEmpty(siteId)){
			try {
				String value = RedisUtil.getString("bike-site-"+siteId);
				if(StringUtil.isNotEmpty(value)){
					bb = JSON.parseObject(value, BikeBean.class);
				}
			} catch (Exception e) {
				logger.error("根据ID[" + siteId + "]获取站点信息时发生异常", e);
			}
		}
		return bb;
	}

	/**
	 * 经纬度纠偏
	 * @param bikes
	 * @param resules
	 * @param convertType default : 0 (百度); 1:腾讯; 2:高德
	 * @return
	 */
	public List<BikeBean> bikeLocalConvert(List<BikeBean> bikes, List<BikeBean> resules, int convertType){
		try {
			return bikeLocalConvert(bikes, resules, convertType, null, null);
		} catch (Exception e) {
			// TODO: handle exception
		}
		return null;
	}
	
	/**
	 * 经纬度纠偏
	 * @param bikes
	 * @param resules
	 * @param convertType
	 * @return
	 * @throws InterruptedException 
	 */
	private synchronized List<BikeBean> bikeLocalConvert(List<BikeBean> bikes, List<BikeBean> resules, int convertType, Boolean isLoop, Integer countFlag ) throws InterruptedException{
		if(convertType == 0){//百度，直接返回
			return bikes;
		}
		boolean flag = false;
		if(null != bikes && bikes.size() > 0){
			flag = true;
		}
		if(null != isLoop){
			flag = isLoop;
		}
		
		List<BikeBean> result = resules;
		int count = 0;
		if(null != countFlag){
			count = countFlag;
		}
		while (flag) {
			
			StringBuffer locations = new StringBuffer();
			List<BikeBean> convertList = new ArrayList<BikeBean>();
			for (int i = 0; i < bikes.size(); i++) {
				if(convertList.size() < 30){
					if(null != bikes.get(i)){
						convertList.add(bikes.get(i));
						String lat = bikes.get(i).getLatitude();
						String lng = bikes.get(i).getLongitude();
						if(convertType == 1){// 腾讯
							locations.append(lat+","+lng+";");
						}else if(convertType == 2){// 高德
							locations.append(lng+","+lat+";");
						}
						
						bikes.remove(i);
						i--;
						//System.out.println(count);
					}
				}else{
					break;
				}
				
			}
			
			ConvertLocalReuslt convertResult = null;
			if(convertType == 1 && null != locations && StringUtil.isNotEmpty(locations.toString())){// 腾讯
				count++;
				System.out.println(count+"%2==0:::::::::"+(count%5));
				if(count%5==0){
					Thread.sleep(4500);
				}
				convertResult = convertLocalQQMapByBaidu(locations);
				System.out.println("需要解析的经纬度："+locations.toString());
				System.out.println("解析前："+convertList.size());
			}else if(convertType == 2 && null != locations && StringUtil.isNotEmpty(locations.toString())){// 高德
				convertResult = convertLocalAMapByBaidu(locations);
			}
			
			if(null != convertResult){
				boolean convertFlag = false;
				if(convertType == 1 && convertResult.getStatus().equals("0")){// 腾讯
					convertFlag = true;
				}else if(convertType == 2 && convertResult.getStatus().equals("1")){// 高德
					convertFlag = true;
				}
				
				if(convertFlag){
					String[] locationArray = convertResult.getLocations().split(";");
					System.out.println("解析后："+locationArray.length);
					for (int i = 0;i < convertList.size(); i++) {
						convertList.get(i).setLnglat(locationArray[i]);
						convertList.get(i).setLongitude(locationArray[i].split(",")[0]);
						convertList.get(i).setLatitude(locationArray[i].split(",")[1]);
					}
					if(null == result){
						result = new ArrayList<BikeBean>();
					}
					result.addAll(convertList);
				}
				
				
			}
			
			if(bikes.size() < 1){
				flag = false;
			}
			bikeLocalConvert(bikes,result, convertType, flag, count);
		}
		
		System.out.println(result.size());
		return result;
	}
	
	/**
	 * 百度经纬度纠偏至高德
	 * @param locations
	 * @return
	 */
	private ConvertLocalReuslt convertLocalAMapByBaidu(StringBuffer locations){
		Map<String, String> parameterMap = new HashMap<String, String>();
		parameterMap.put("key", "6ff97f49dce4dc604d1a739c2a3a6f83");
		parameterMap.put("locations",locations.toString());
		parameterMap.put("coordsys","baidu");
		parameterMap.put("output","JSON");
		String str = HttpClientUtils.doPost("http://restapi.amap.com/v3/assistant/coordinate/convert", null, parameterMap);
		ConvertLocalReuslt result = JSON.parseObject(str, ConvertLocalReuslt.class);
		return result;
	}
	
	/**
	 * 百度经纬度纠偏至腾讯
	 * @param locations
	 * @return
	 */
	private synchronized ConvertLocalReuslt convertLocalQQMapByBaidu(StringBuffer locations){
		String local = locations.toString();
		ConvertLocalReuslt result = null;
		if(StringUtil.isNotEmpty(local)){
			Map<String, String> parameterMap = new HashMap<String, String>();
			//parameterMap.put("key", "N7LBZ-H3PAX-SWI4O-Z7XSN-HD5H5-4MBV7");
			parameterMap.put("key", "KVJBZ-GFP2X-CVE42-74ZFF-XUGTE-WSBZH");
			parameterMap.put("locations",local.substring(0, local.length()-1));
			parameterMap.put("type","3");//1 GPS坐标  2 sogou经纬度  3 baidu经纬度   4 mapbar经纬度    5 [默认]腾讯、google、高德坐标    6 sogou墨卡托
			parameterMap.put("output","JSON");
			String str = HttpClientUtils.doGet("http://apis.map.qq.com/ws/coord/v1/translate", parameterMap);
			result = JSON.parseObject(str, ConvertLocalReuslt.class);
			if(!result.getStatus().equals("0")){
				System.out.println(str);
			}
		}else{
			System.out.println("空了");
		}
		return result;
	}
	

}
